/*
 * This file is part of the Sx Framework Library.
 * 
 * Copyright (C) 2013 University of Colorado Denver
 * <min.choi@ucdenver.edu>
 * <shane.transue@ucdenver.edu>
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy 
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 
 * copies of the Software, and to permit persons to whom the Software is 
 * furnished to do so, subject to the following conditions:
 * 
 * The above copyright notice and this permission notice shall be included in 
 * all copies or substantial portions of the Software.
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
 * DEALINGS IN THE SOFTWARE.
 */
#ifndef SX_QDEBUGSTREAM_H
#define SX_QDEBUGSTREAM_H

#include <QObject>
#include <sxString.h>
#include <streambuf>
#include <fstream>

namespace Sx {
namespace QtInterface {
namespace System {

class QConsole;
typedef std::basic_streambuf<char, std::char_traits<char> >::int_type int_type;

/*
 * Creates a debug stream that redirects a standard output stream to a console
 * as well as a file. This class is intended to provide constant logging
 * information accessable from both the user interface and separately in
 * a log file for application errors.
 */
class QDebugStream : public QObject, public std::basic_streambuf<char> {
	Q_OBJECT

public:
	/*
	 * stream - The standard stream to be redirected.
	 * console - The QConsole that will have the standard stream appended to 
	 *  its current text.
	 * logFilename - The name of the log file that will be created while the 
	 *  application is running.
	 */
	QDebugStream(std::ostream* stream, QConsole* console, const String& logFilename, bool append = true);
	~QDebugStream();

	/*
	 * Sets the stream that is redirected by this debug stream.
	 */
	void setStream(std::ostream* stream);

	void setLogFilename(const String& filename);

	/*
	 * Returns the log filename associated with this debug stream.
	 */
	const String& getLogFilename() const;

protected:
	int_type overflow(int_type v);
	std::streamsize xsputn(const char* p, std::streamsize n);

signals:
	/*
	 * To ensure that the append operations are thread safe, the following
	 * signals can be used to send the strings to Qt based text objects.
	 * When the signals are received by the text object in the GUI thread
	 * they can be appended to the objects current text.
	 */
	void onAppend(const QString& text);
	void onLogAppend(const QString& text);

private:
	/*
	 * The provided standard stream is redirected to this console. Each
	 * stream operation will be appended to the existing text contained
	 * in the console. This console is configured to be efficient for
	 * logging purposes.
	 *
	 * Pointer Ownership: NO
	 */
	QConsole* console;
	String data;
	String logFilename;

	/*
	 * These hold the state of the old stream before it has been redirected
	 * to this console.
	 *
	 * Pointer Ownership: NO
	 */
	std::ostream* stream;

	/*
	 * Used as a temporary store for the stream buffer.
	 *
	 * Pointer Ownership: NO
	 */
	std::streambuf* originalBuf;
};

}

}

}

#endif
